// -*-mode:c++; coding:utf-8-*-

#ifndef _XBASE_PROTOCOL_BASE_HPP_
#define _XBASE_PROTOCOL_BASE_HPP_

#include <sstream>
#include <limits>
#include <cassert>

#include <boost/cast.hpp>
#include <boost/shared_ptr.hpp>

#include "byteorder.hpp"
#include "binary_iarchive.hpp"
#include "binary_oarchive.hpp"
#include "error_code.hpp"
#include "stringable.hpp"

namespace xbase
{
	namespace protocol
	{
		typedef ::kb::network_byteorder byteorder;

		typedef ::kb::binary_iarchive<byteorder> iarchive;
		typedef ::kb::binary_oarchive<byteorder> oarchive;
	
		static const std::size_t P_BUFFER_SIZE = 1024 * 1024; // 协议包通常的大小，但不是最大大小
			
		static const uint16_t P_MAGIC_NUMBER = 0x11DE;
		static const uint16_t P_VERSION = 1;
		static const std::size_t P_BAD_SEQUENCE = std::numeric_limits<uint32_t>::max();

		// 
		// 协议类型值的规则
		//
		// 偶数为请求，奇数为响应；协议值递增分配，没用完之前尽量不要重
		// 用以前用过的。
		// 
		enum type_code
		{
			// 1. 查询根子表信息
			ROOT_META_REQ = 0x0000,
			ROOT_META_RESP = 0x0001,

			// 2. 向主服务器查询某个表的结构信息
			TABLE_INFO_REQ = 0x0002,
			TABLE_INFO_RESP = 0x0003,

			// 3. 创建表
			CREATE_TABLE_REQ = 0x0004,
			CREATE_TABLE_RESP = 0x0005,

			// 4. 为某个表添加列族
			ADD_FAMILY_REQ = 0x0006,
			ADD_FAMILY_RESP = 0x0007,

			// 5. 为某个表删除列族
			DELETE_FAMILY_REQ = 0x0008,
			DELETE_FAMILY_RESP = 0x0009,

			// 6. 添加某个表的组
			ADD_GROUP_REQ = 0x000A,
			ADD_GROUP_RESP = 0x000B,

			// 7. 删除某个表的组
			DELETE_GROUP_REQ = 0x000C,
			DELETE_GROUP_RESP = 0x000D,

			// 8. 删除表
			DELETE_TABLE_REQ = 0x000E,
			DELETE_TABLE_RESP = 0x000F,

			// 1. 读记录
			READ_REQ = 0x0010,
			READ_RESP = 0x0011,

			// 2. 写记录
			WRITE_REQ = 0x0012,
			WRITE_RESP = 0x0013,

			// 3. 扫描/遍历记录
			SCAN_OPEN_REQ = 0x0014,
			SCAN_OPEN_RESP = 0x0015,

			SCAN_NEXT_REQ = 0x0016,
			SCAN_NEXT_RESP = 0x0017,

			SCAN_CLOSE_REQ = 0x0018,
			SCAN_CLOSE_RESP = 0x0019,

			// 1. 启动时，向主服务器发送报到消息
			TABLET_SERVER_REPORT = 0x001A,

			// 2. 运行过程中，向主服务器发送心跳信息
			HEARTBEAT_REQ = 0x001C,

			// 3. 主服务器向子表服务器发送加载子表命令
			LOAD_TABLET_REQ = 0x001E,
			LOAD_TABLET_RESP = 0x001F,

			// 4. 删除子表
			REMOVE_TABLET_REQ = 0x0020,
			REMOVE_TABLET_RESP = 0x0021,

			// 5. 子表分裂后，向主服务器报告哪个子表分裂成了哪两个子表
			TABLET_SPLIT_REPORT = 0x0022,

			// 6. 子表服务器退出时，向主服务器发送下线消息
			TABLET_SERVER_QUIT = 0x0024,
    
			//7. 主服务器要求子表服务器重启
			TABLET_SERVER_RESTART = 0x0026,

			// 列子表
			LIST_TABLET_REQ = 0x0028,
			LIST_TABLET_RESP = 0x0029,

			// 列表
			LIST_TABLE_REQ = 0x002A,
			LIST_TABLE_RESP = 0x002B,

			// 批量写
			BATCH_WRITE_REQ = 0x002C,
			BATCH_WRITE_RESP = 0x002D,

			COMMAND_COUNT,  //命令总数，不作命令ID
			P_BAD_TYPE_CODE
		};

		const char *type_name(type_code type);

		class packet
			: public stringable
		{
		public:
			enum
			{
				// 每个字段的字节偏移量
				POS_MAGIC = 0,
				POS_VERSION = 2,
				POS_TYPE = 3,
				POS_SEQUENCE_NUMBER = 5,
				POS_DATA_LENGTH = 9,

				// 及总的字节数
				HEADER_SIZE = 13
			};
			
		public:
			packet()
				: m_magic(P_MAGIC_NUMBER)
				, m_version(P_VERSION)
				, m_type(P_BAD_TYPE_CODE)
				, m_sequence_number(P_BAD_SEQUENCE)
				, m_data_length(0) {}

			packet(type_code type,
			       std::size_t sequence_number,
			       std::size_t data_length)
				: m_magic(P_MAGIC_NUMBER)
				, m_version(P_VERSION)
				, m_type(static_cast<uint16_t>(type))
				, m_sequence_number(static_cast<uint32_t>(sequence_number))
				, m_data_length(static_cast<uint32_t>(data_length)) {
				assert(sequence_number <= static_cast<std::size_t>(std::numeric_limits<uint32_t>::max()));
				assert(data_length <= static_cast<std::size_t>(std::numeric_limits<uint32_t>::max()));
			}

			virtual
			~packet() {}

			template<typename IArchive>
			bool load(IArchive &in) {
				return in.load(&m_magic) &&
					in.load(&m_version) &&
					in.load(&m_type) &&
					in.load(&m_sequence_number) &&
					in.load(&m_data_length);
			}

			template<typename OArchive>
			bool save(OArchive &out) const {
				return out.save(m_magic) &&
					out.save(m_version) &&
					out.save(m_type) &&
					out.save(m_sequence_number) &&
					out.save(m_data_length);
			}

			virtual
			std::string to_string() const;

			type_code get_type() const {
				return static_cast<type_code>(m_type);
			}

			std::size_t get_sequence_number() const {
				return static_cast<std::size_t>(m_sequence_number);
			}

			std::size_t get_data_length() const {
				return static_cast<std::size_t>(m_data_length);
			}

			void set_sequence_number(std::size_t seq) {
				assert(seq <= static_cast<std::size_t>(std::numeric_limits<uint32_t>::max()));
				m_sequence_number = static_cast<uint32_t>(seq);
			}

			void set_data_length(std::size_t length) {
				assert(length <= static_cast<std::size_t>(std::numeric_limits<uint32_t>::max()));
				m_data_length = static_cast< uint32_t >(length);
			}
			
		private:
			uint16_t m_magic;  // 魔数
			uint8_t m_version; // 协议版本号
			uint16_t m_type;
			uint32_t m_sequence_number;
			uint32_t m_data_length;
		};

		typedef boost::shared_ptr<packet> packet_ptr;

		template<typename T>
		class basic_packet
			: public packet
		{
		public:
			typedef basic_packet<T> this_type;
			
			typedef T value_type;
			//typedef T element_type;

			// get type code by type code tag or user defined tag
			static const type_code type = T::type;

		private:
			T m_body;

		public:
			explicit
			basic_packet(std::size_t sequence_number = P_BAD_SEQUENCE)
				: packet(type,
					 sequence_number,
					 0)
				, m_body() {}

			template<typename IArchive>
			bool load(IArchive &in) {
				return packet::load(in) &&
					m_body.load(in);
			}

			template<typename OArchive>
			bool save(OArchive &out) const {
				char * const buf = out.left_buffer();
				const std::size_t left_size = out.left_buffer_size(); 
				const bool ok = packet::save(out) && m_body.save(out);
				if(ok) {
					// 设置data_length字段（不改变自己的值）
					const std::size_t data_length = left_size - out.left_buffer_size() - packet::HEADER_SIZE;
					assert(data_length <= static_cast<std::size_t>(std::numeric_limits<uint32_t>::max()));
					const uint32_t len = static_cast<uint32_t>(data_length);
					char * const data_length_buf = buf + packet::POS_DATA_LENGTH;
					OArchive out_data_length(data_length_buf, sizeof(len));
					out_data_length << len;
				}
				return ok;
			}

			T &body() {
				return m_body;
			}

			const T &body() const {
				return m_body;
			}

			virtual
			std::string to_string() const {
				std::ostringstream out;
				out << "{header: " << packet::to_string()
				    << "; body: " << m_body.to_string()
				    << "}";
				return out.str();
			}
		};

		template<type_code code>
		struct packet_type
		{
			typedef packet type;
			typedef packet_ptr ptr_type;
		};

		// 验证包
		// 
		// 依次检查包头是否足够，以及magic是否正确，包是否完整；
		//
		// end - 若包完整，则end将被置为包结束位置，否则不修改；
		// bytes_to_read - 若包不完整，则为缺失部分的长度，否则为0；
		// id - 若包完整，则为包中的sequence_number；否则不修改；
		//
		// 可返回的错误： header_incomplete, bad_magic, packet_incomplete
		boost::system::error_code validate(const char *begin,
						   const char **end,
						   std::size_t *bytes_to_read,
						   std::size_t *id,
						   boost::system::error_code &ec);

	} // namespace protocol

} // namespace xbase

#endif	// _XBASE_PROTOCOL_BASE_HPP_

